package com.sukaiyi.leetcode._202happy_number;

import org.junit.jupiter.api.Test;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * 快乐数
 * <p>
 * 编写一个算法来判断一个数 n 是不是快乐数。
 * 「快乐数」定义为：对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和，然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。如果 可以变为  1，那么这个数就是快乐数。
 * 如果 n 是快乐数就返回 True ；不是，则返回 False
 *
 * @author sukaiyi
 * @date 2020/04/30
 * @see <a href="https://leetcode-cn.com/problems/happy-number/">题目地址</a>
 */
public class Solution {

    @Test
    public void test() {
        assertFalse(isHappy(162));
        assertTrue(isHappy(19));
        assertFalse(isHappy(2));
    }

    static Set<Integer> loopNums = new HashSet<Integer>() {{
        add(0);
        add(2);
    }};
    static Set<Integer> happyNums = new HashSet<Integer>() {{
        add(1);
        add(10);
        add(100);
    }};

    public boolean isHappy(int n) {
        if (loopNums.contains(n)) {
            return false;
        }
        if (happyNums.contains(n)) {
            return true;
        }

        Set<Integer> workSet = new HashSet<>();
        workSet.add(n);
        int powerSum = n;
        while (true) {
            powerSum = powerSum(powerSum);
            if (powerSum == 1) {
                happyNums.addAll(workSet);
                return true;
            } else if (workSet.contains(powerSum)) {
                loopNums.addAll(workSet);
                return false;
            }
            workSet.add(powerSum);
        }
    }

    private int powerSum(int nn) {
        int powerSum = 0;
        while (nn > 0) {
            int mod = nn % 10;
            powerSum += mod * mod;
            nn = nn / 10;
        }
        return powerSum;
    }

}
